package cn.iocoder.yudao.module.scrm.aop;

import cn.iocoder.yudao.module.scrm.annotations.InterfaceDeleteValidator;
import cn.iocoder.yudao.module.scrm.enums.common.CrmBizTypeEnum;
import cn.iocoder.yudao.module.scrm.strategy.DeleteStrategy;
import cn.iocoder.yudao.module.scrm.strategy.DeleteStrategyFactory;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.scrm.enums.ErrorCodeConstants.COMPARE_STRATEGY_TYPE_NOT_NULL;

/**
 * @Author LiZhiMin
 * @Date 2024/9/13 9:26
 */
@Aspect
@Component
@Slf4j
public class InterfaceDeleteAspect {


    @Autowired
    private DeleteStrategyFactory deleteStrategyFactory;

    /**
     * 切点方法，用于在被 {@link InterfaceDeleteValidator} 注解标记的方法执行之前触发。
     * <p>
     * 从注解中提取字段比较配置，并根据这些配置选择并执行相应的比较策略。
     * 该方法获取方法参数，提取比较需要的字段信息，并通过 {@link DeleteStrategyFactory} 获取对应的比较策略进行验证。
     * </p>
     *
     * @param joinPoint                连接点，提供了方法执行的信息和上下文。
     * @param interfaceDeleteValidator 自定义注解 {@link InterfaceDeleteValidator}，提供字段比较的配置信息。
     */
    @Before("@annotation(interfaceDeleteValidator)")
    public void pointcut(JoinPoint joinPoint, InterfaceDeleteValidator interfaceDeleteValidator) {
        // 获取方法参数
        Object[] args = joinPoint.getArgs();
        // 从注解中提取主表枚举类型
        CrmBizTypeEnum tableTypeEnum = interfaceDeleteValidator.tableType();
        // 获取要查询的主表字段名
        CrmBizTypeEnum strategyTypeEnum = interfaceDeleteValidator.strategyType();

        // 从工厂获取对应的比较策略
        DeleteStrategy strategy = deleteStrategyFactory.getStrategy(tableTypeEnum, strategyTypeEnum);

        if (strategy != null) {
            // 执行策略进行字段比较验证
            strategy.deleteCheck((Long) args[0]);
        } else {
            // 如果未找到对应的策略，则抛出异常
            throw exception(COMPARE_STRATEGY_TYPE_NOT_NULL);
        }

    }

}
